﻿Imports ACompany.OrderProcessing.Model
Imports ACompany.OrderProcessing.Infrastructure
Imports ACompany.OrderProcessing.NhibernateRepository

Public Class ProductService
    Implements IProductService

    Private _ProductRepository As IProductRepository
    Private _OrderService As IOrderService
    Private _UnitOfWork As IUnitOfWork

    Public Sub New(ByVal ProductRepository As IProductRepository, ByVal OrderService As IOrderService, ByVal UnitOfWork As IUnitOfWork)
        Me._ProductRepository = ProductRepository
        Me._ProductRepository.Inject(UnitOfWork)

        Me._OrderService = OrderService

        Me._UnitOfWork = UnitOfWork
    End Sub

    Public Function FindAll() As System.Collections.Generic.List(Of Model.Product) Implements Model.IProductService.FindAll
        Return _ProductRepository.FindAll
    End Function

    Public Sub Save(ByVal Product As Model.Product) Implements Model.IProductService.Save
        If Product.GetBrokenRules.Count = 0 Then
            Me._ProductRepository.Save(Product)
            _UnitOfWork.Commit()
        Else

            Dim brokenRules As String = BuildErrorListFrom(Product)

            Throw New InvalidOperationException( _
                String.Format("You cannot save the product because it has broken business rules. {0}", brokenRules))

        End If
    End Sub

    Private Function BuildErrorListFrom(ByVal Product As Product) As String

        Dim brokenRulesList As New Text.StringBuilder

        For Each brokenRule As BrokenRule In Product.GetBrokenRules
            brokenRulesList.Append(brokenRule.Rule)
            brokenRulesList.Append(Environment.NewLine)
        Next

        Return brokenRulesList.ToString

    End Function

    Public Function FindBy(ByVal Id As Guid) As Model.Product Implements Model.IProductService.FindBy
        Return Me._ProductRepository.FindBy(Id)
    End Function

    Public Function CanRemove(ByVal Product As Product) As Boolean
        Return _OrderService.FindAllOrdersContainingProductBy(Product.Id).Count = 0
    End Function

    Public Sub Remove(ByVal Product As Model.Product) Implements Model.IProductService.Remove

        If CanRemove(Product) Then

            _ProductRepository.Remove(Product)
            _UnitOfWork.Commit()

        Else
            Throw New ApplicationException("This product cannot be removed as it is linked to orders")
        End If

    End Sub
End Class
